home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / liboctave / Array2-idx.h < prev    next >
C/C++ Source or Header  |  1997-08-01  |  14KB  |  661 lines

  1. // Template array classes
  2. /*
  3.  
  4. Copyright (C) 1996 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22. */
  23.  
  24. #include "Array-flags.h"
  25. #include "idx-vector.h"
  26. #include "lo-error.h"
  27.  
  28. template <class T>
  29. Array2<T>
  30. Array2<T>::value (void)
  31. {
  32.   Array2<T> retval;
  33.  
  34.   int n_idx = index_count ();
  35.  
  36.   if (n_idx == 2)
  37.     {
  38.       idx_vector *tmp = get_idx ();
  39.       idx_vector idx_i = tmp[0];
  40.       idx_vector idx_j = tmp[1];
  41.  
  42.       return index (idx_i, idx_j);
  43.     }
  44.   else if (n_idx == 1)
  45.     {
  46.       idx_vector *tmp = get_idx ();
  47.       idx_vector idx = tmp[0];
  48.  
  49.       return index (idx);
  50.     }
  51.   else
  52.     (*current_liboctave_error_handler)
  53.       ("invalid number of indices for matrix expression");
  54.  
  55.   clear_index ();
  56.  
  57.   return retval;
  58. }
  59.  
  60. template <class T>
  61. Array2<T>
  62. Array2<T>::index (idx_vector& idx) const
  63. {
  64.   Array2<T> retval;
  65.  
  66.   int nr = d1;
  67.   int nc = d2;
  68.  
  69.   if (nr == 1 && nc == 1)
  70.     {
  71.       Array<T> tmp = Array<T>::index (idx);
  72.  
  73.       int len = tmp.length ();
  74.  
  75.       if (len == 0)
  76.     retval = Array2<T> (0, 0);
  77.       else
  78.     {
  79.       if (liboctave_pcv_flag)
  80.         retval = Array2<T> (tmp, len, 1);
  81.       else
  82.         retval = Array2<T> (tmp, 1, len);
  83.     }
  84.     }
  85.   else if (nr == 1 || nc == 1)
  86.     {
  87.       int result_is_column_vector = (nc == 1);
  88.  
  89.       if (liboctave_dfi_flag && idx.is_colon ())
  90.         result_is_column_vector = 1;
  91.  
  92.       Array<T> tmp = Array<T>::index (idx);
  93.  
  94.       int len = tmp.length ();
  95.  
  96.       if (len == 0)
  97.     retval = Array2<T> (0, 0);
  98.       else
  99.     {
  100.       if (result_is_column_vector)
  101.         retval = Array2<T> (tmp, len, 1);
  102.       else
  103.         retval = Array2<T> (tmp, 1, len);
  104.     }
  105.     }
  106.   else if (liboctave_dfi_flag)
  107.     {
  108.       // This code is only for indexing matrices.  The vector
  109.       // cases are handled above.
  110.  
  111.       idx.freeze (nr * nc, "matrix", liboctave_pzo_flag);
  112.  
  113.       if (idx)
  114.     {
  115.       int result_nr = idx.orig_rows ();
  116.       int result_nc = idx.orig_columns ();
  117.  
  118.       if (idx.is_colon ())
  119.         {
  120.           result_nr = nr * nc;
  121.           result_nc = result_nr ? 1 : 0;
  122.         }
  123.       else if (idx.one_zero_only ())
  124.         {
  125.           result_nr = idx.ones_count ();
  126.           result_nc = (result_nr > 0 ? 1 : 0);
  127.         }
  128.  
  129.       retval.resize (result_nr, result_nc);
  130.  
  131.       int k = 0;
  132.       for (int j = 0; j < result_nc; j++)
  133.         {
  134.           for (int i = 0; i < result_nr; i++)
  135.         {
  136.           int ii = idx.elem (k++);
  137.           int fr = ii % nr;
  138.           int fc = (ii - fr) / nr;
  139.           retval.elem (i, j) = elem (fr, fc);
  140.         }
  141.         }
  142.     }
  143.       // idx_vector::freeze() printed an error message for us.
  144.     }
  145.   else
  146.     (*current_liboctave_error_handler)
  147.       ("single index only valid for row or column vector");
  148.  
  149.   return retval;
  150. }
  151.  
  152. template <class T>
  153. Array2<T>
  154. Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j) const
  155. {
  156.   Array2<T> retval;
  157.  
  158.   int nr = d1;
  159.   int nc = d2;
  160.  
  161.   int n = idx_i.freeze (nr, "row", liboctave_pzo_flag);
  162.   int m = idx_j.freeze (nc, "column", liboctave_pzo_flag);
  163.  
  164.   if (idx_i && idx_j)
  165.     {
  166.       if (idx_i.orig_empty () || idx_j.orig_empty ())
  167.     {
  168.       retval.resize (n, m);
  169.     }
  170.       else if (n == 0)
  171.     {
  172.       if (m == 0)
  173.         retval.resize (0, 0);
  174.       else if (idx_j.is_colon_equiv (nc, 1))
  175.         retval.resize (0, nc);
  176.       else
  177.         (*current_liboctave_error_handler) ("invalid row index = 0");
  178.     }
  179.       else if (m == 0)
  180.     {
  181.       if (n == 0)
  182.         retval.resize (0, 0);
  183.       else if (idx_i.is_colon_equiv (nr, 1))
  184.         retval.resize (nr, 0);
  185.       else
  186.         (*current_liboctave_error_handler) ("invalid column index = 0");
  187.     }
  188.       else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc))
  189.     {
  190.       retval = *this;
  191.     }
  192.       else
  193.     {
  194.       retval.resize (n, m);
  195.  
  196.       for (int j = 0; j < m; j++)
  197.         {
  198.           int jj = idx_j.elem (j);
  199.           for (int i = 0; i < n; i++)
  200.         {
  201.           int ii = idx_i.elem (i);
  202.           retval.elem (i, j) = elem (ii, jj);
  203.         }
  204.         }
  205.     }
  206.     }
  207.  
  208.   // idx_vector::freeze() printed an error message for us.
  209.  
  210.   return retval;
  211. }
  212.  
  213. template <class T>
  214. void
  215. Array2<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j)
  216. {
  217.   int nr = d1;
  218.   int nc = d2;
  219.  
  220.   if (nr == 0 && nc == 0)
  221.     return;
  222.  
  223.   if (idx_i.is_colon_equiv (nr, 1))
  224.     {
  225.       if (idx_j.is_colon_equiv (nc, 1))
  226.     resize (0, 0);
  227.       else
  228.     {
  229.       idx_j.sort (true);
  230.  
  231.       int num_to_delete = idx_j.length (nc);
  232.  
  233.       if (num_to_delete != 0)
  234.         {
  235.           if (nr == 1 && num_to_delete == nc)
  236.         resize (0, 0);
  237.           else
  238.         {
  239.           int new_nc = nc;
  240.  
  241.           int idx = 0;
  242.  
  243.           for (int j = 0; j < nc; j++)
  244.             if (j == idx_j.elem (idx))
  245.               {
  246.             idx++;
  247.             new_nc--;
  248.  
  249.             if (idx == num_to_delete)
  250.               break;
  251.               }
  252.  
  253.           if (new_nc > 0)
  254.             {
  255.               T *new_data = new T [nr * new_nc];
  256.  
  257.               int jj = 0;
  258.               idx = 0;
  259.               for (int j = 0; j < nc; j++)
  260.             {
  261.               if (idx < num_to_delete && j == idx_j.elem (idx))
  262.                 idx++;
  263.               else
  264.                 {
  265.                   for (int i = 0; i < nr; i++)
  266.                 new_data[nr*jj+i] = elem (i, j);
  267.                   jj++;
  268.                 }
  269.             }
  270.  
  271.               if (--rep->count <= 0)
  272.             delete rep;
  273.  
  274.               rep = new ArrayRep (new_data, nr * new_nc);
  275.  
  276.               d2 = new_nc;
  277.  
  278.               set_max_indices (2);
  279.             }
  280.           else
  281.             (*current_liboctave_error_handler)
  282.               ("A(idx) = []: index out of range");
  283.         }
  284.         }
  285.     }
  286.     }
  287.   else if (idx_j.is_colon_equiv (nc, 1))
  288.     {
  289.       if (idx_i.is_colon_equiv (nr, 1))
  290.     resize (0, 0);
  291.       else
  292.     {
  293.       idx_i.sort (true);
  294.  
  295.       int num_to_delete = idx_i.length (nr);
  296.  
  297.       if (num_to_delete != 0)
  298.         {
  299.           if (nc == 1 && num_to_delete == nr)
  300.         resize (0, 0);
  301.           else 
  302.         {
  303.           int new_nr = nr;
  304.  
  305.           int idx = 0;
  306.  
  307.           for (int i = 0; i < nr; i++)
  308.             if (i == idx_i.elem (idx))
  309.               {
  310.             idx++;
  311.             new_nr--;
  312.  
  313.             if (idx == num_to_delete)
  314.               break;
  315.               }
  316.  
  317.           if (new_nr > 0)
  318.             {
  319.               T *new_data = new T [new_nr * nc];
  320.  
  321.               int ii = 0;
  322.               idx = 0;
  323.               for (int i = 0; i < nr; i++)
  324.             {
  325.               if (idx < num_to_delete && i == idx_i.elem (idx))
  326.                 idx++;
  327.               else
  328.                 {
  329.                   for (int j = 0; j < nc; j++)
  330.                 new_data[new_nr*j+ii] = elem (i, j);
  331.                   ii++;
  332.                 }
  333.             }
  334.  
  335.               if (--rep->count <= 0)
  336.             delete rep;
  337.  
  338.               rep = new ArrayRep (new_data, new_nr * nc);
  339.  
  340.               d1 = new_nr;
  341.  
  342.               set_max_indices (2);
  343.             }
  344.           else
  345.             (*current_liboctave_error_handler)
  346.               ("A(idx) = []: index out of range");
  347.         }
  348.         }
  349.     }
  350.     }
  351. }
  352.  
  353. #define MAYBE_RESIZE_LHS \
  354.   do \
  355.     { \
  356.       if (liboctave_rre_flag) \
  357.     { \
  358.       int max_row_idx = idx_i_is_colon ? rhs_nr : idx_i.max () + 1; \
  359.       int max_col_idx = idx_j_is_colon ? rhs_nc : idx_j.max () + 1; \
  360.  \
  361.       int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \
  362.       int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \
  363.  \
  364.       lhs.resize (new_nr, new_nc, 0.0); \
  365.     } \
  366.     } \
  367.   while (0)
  368.  
  369. template <class LT, class RT>
  370. int
  371. assign (Array2<LT>& lhs, const Array2<RT>& rhs)
  372. {
  373.   int retval = 1;
  374.  
  375.   int n_idx = lhs.index_count ();
  376.  
  377.   int lhs_nr = lhs.rows ();
  378.   int lhs_nc = lhs.cols ();
  379.  
  380.   int rhs_nr = rhs.rows ();
  381.   int rhs_nc = rhs.cols ();
  382.  
  383.   if (n_idx == 2)
  384.     {
  385.       idx_vector *tmp = lhs.get_idx ();
  386.  
  387.       idx_vector idx_i = tmp[0];
  388.       idx_vector idx_j = tmp[1];
  389.  
  390.       int n = idx_i.freeze (lhs_nr, "row", liboctave_pzo_flag,
  391.                 liboctave_rre_flag);
  392.  
  393.       int m = idx_j.freeze (lhs_nc, "column", liboctave_pzo_flag,
  394.                 liboctave_rre_flag);
  395.  
  396.       int idx_i_is_colon = idx_i.is_colon ();
  397.       int idx_j_is_colon = idx_j.is_colon ();
  398.  
  399.       if (idx_i_is_colon)
  400.     n = lhs_nr > 0 ? lhs_nr : rhs_nr;
  401.  
  402.       if (idx_j_is_colon)
  403.     m = lhs_nc > 0 ? lhs_nc : rhs_nc;
  404.  
  405.       if (idx_i && idx_j)
  406.     {
  407.       if (rhs_nr == 0 && rhs_nc == 0)
  408.         {
  409.           lhs.maybe_delete_elements (idx_i, idx_j);
  410.         }
  411.       else
  412.         {
  413.           if (rhs_nr == 1 && rhs_nc == 1 && n > 0 && m > 0)
  414.         {
  415.           MAYBE_RESIZE_LHS;
  416.  
  417.           RT scalar = rhs.elem (0, 0);
  418.  
  419.           for (int j = 0; j < m; j++)
  420.             {
  421.               int jj = idx_j.elem (j);
  422.               for (int i = 0; i < n; i++)
  423.             {
  424.               int ii = idx_i.elem (i);
  425.               lhs.elem (ii, jj) = scalar;
  426.             }
  427.             }
  428.         }
  429.           else if (n == rhs_nr && m == rhs_nc)
  430.         {
  431.           MAYBE_RESIZE_LHS;
  432.  
  433.           for (int j = 0; j < m; j++)
  434.             {
  435.               int jj = idx_j.elem (j);
  436.               for (int i = 0; i < n; i++)
  437.             {
  438.               int ii = idx_i.elem (i);
  439.               lhs.elem (ii, jj) = rhs.elem (i, j);
  440.             }
  441.             }
  442.         }
  443.           else
  444.         {
  445.           (*current_liboctave_error_handler)
  446.     ("A(I, J) = X: X must be a scalar or the number of elements in I must");
  447.           (*current_liboctave_error_handler)
  448.     ("match the number of rows in X and the number of elements in J must");
  449.           (*current_liboctave_error_handler)
  450.     ("match the number of columns in X");
  451.  
  452.           retval = 0;
  453.         }
  454.         }
  455.     }
  456.       // idx_vector::freeze() printed an error message for us.
  457.     }
  458.   else if (n_idx == 1)
  459.     {
  460.       int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0;
  461.  
  462.       if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1))
  463.     {
  464.       idx_vector *tmp = lhs.get_idx ();
  465.  
  466.       idx_vector idx = tmp[0];
  467.  
  468.       int lhs_len = lhs.length ();
  469.  
  470.       int n = idx.freeze (lhs_len, 0, liboctave_pzo_flag,
  471.                   liboctave_rre_flag);
  472.  
  473.       if (idx)
  474.         {
  475.           if (rhs_nr == 0 && rhs_nc == 0)
  476.         {
  477.           if (n != 0 && (lhs_nr != 0 || lhs_nc != 0))
  478.             {
  479.               idx_vector tmp (':');
  480.               lhs.maybe_delete_elements (idx, tmp);
  481.             }
  482.         }
  483.           else if (! liboctave_dfi_flag && lhs_is_empty
  484.                && idx.is_colon ()
  485.                && ! (rhs_nr == 1 || rhs_nc == 1))
  486.         {
  487.           (*current_liboctave_error_handler)
  488.             ("A(:) = X: X must be a vector");
  489.         }
  490.           else
  491.         {
  492.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  493.             {
  494.               int len = lhs.length ();
  495.  
  496.               if (len > 0)
  497.             {
  498.               int idx_nr = idx.orig_rows ();
  499.               int idx_nc = idx.orig_columns ();
  500.  
  501.               // lhs_is_empty now means that lhs was
  502.               // *originally* empty.
  503.  
  504.               if (liboctave_dfi_flag
  505.                   || (idx_nr == 1 && idx_nc == 1))
  506.                 {
  507.                   if (liboctave_pcv_flag)
  508.                 {
  509.                   lhs.d1 = lhs.length ();
  510.                   lhs.d2 = 1;
  511.                 }
  512.                   else
  513.                 {
  514.                   lhs.d1 = 1;
  515.                   lhs.d2 = lhs.length ();
  516.                 }
  517.                 }
  518.               else if (lhs_is_empty && idx.is_colon ())
  519.                 {
  520.                   lhs.d1 = rhs.d1;
  521.                   lhs.d2 = rhs.d2;
  522.                 }
  523.               else if (idx_nr == 1 && rhs_nr == 1)
  524.                 {
  525.                   lhs.d1 = 1;
  526.                   lhs.d2 = lhs.length ();
  527.                 }
  528.               else if (idx_nc == 1 && rhs_nc == 1)
  529.                 {
  530.                   lhs.d1 = lhs.length ();
  531.                   lhs.d2 = 1;
  532.                 }
  533.               else
  534.                 (*current_liboctave_error_handler)
  535.       ("A(I) = X: X must be a scalar or a matrix with the same size as I");
  536.             }
  537.               else
  538.             {
  539.               lhs.d1 = 0;
  540.               lhs.d2 = 0;
  541.             }
  542.             }
  543.           else
  544.             retval = 0;
  545.         }
  546.         }
  547.       // idx_vector::freeze() printed an error message for us.
  548.     }
  549.       else if (lhs_nr == 1)
  550.     {
  551.       idx_vector *tmp = lhs.get_idx ();
  552.  
  553.       idx_vector idx = tmp[0];
  554.  
  555.       idx.freeze (lhs_nc, "vector", liboctave_pzo_flag,
  556.               liboctave_rre_flag);
  557.  
  558.       if (idx)
  559.         {
  560.           if (rhs_nr == 0 && rhs_nc == 0)
  561.         {
  562.           idx_vector tmp (':');
  563.           lhs.maybe_delete_elements (tmp, idx);
  564.         }
  565.           else
  566.         {
  567.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  568.             lhs.d2 = lhs.length ();
  569.           else
  570.             retval = 0;
  571.         }
  572.         }
  573.       // idx_vector::freeze() printed an error message for us.
  574.     }
  575.       else if (lhs_nc == 1)
  576.     {
  577.       idx_vector *tmp = lhs.get_idx ();
  578.  
  579.       idx_vector idx = tmp[0];
  580.  
  581.       idx.freeze (lhs_nr, "vector", liboctave_pzo_flag,
  582.               liboctave_rre_flag);
  583.  
  584.       if (idx)
  585.         {
  586.           if (rhs_nr == 0 && rhs_nc == 0)
  587.         {
  588.           idx_vector tmp (':');
  589.           lhs.maybe_delete_elements (idx, tmp);
  590.         }
  591.           else
  592.         {
  593.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  594.             lhs.d1 = lhs.length ();
  595.           else
  596.             retval = 0;
  597.         }
  598.         }
  599.       // idx_vector::freeze() printed an error message for us.
  600.     }
  601.       else if (liboctave_dfi_flag)
  602.     {
  603.       idx_vector *tmp = lhs.get_idx ();
  604.       idx_vector idx = tmp[0];
  605.  
  606.       int len = idx.freeze (lhs_nr * lhs_nc, "matrix",
  607.                 liboctave_pzo_flag);
  608.  
  609.       if (idx)
  610.         {
  611.           if (len == rhs_nr * rhs_nc)
  612.         {
  613.           int k = 0;
  614.           for (int j = 0; j < rhs_nc; j++)
  615.             {
  616.               for (int i = 0; i < rhs_nr; i++)
  617.             {
  618.               int ii = idx.elem (k++);
  619.               int fr = ii % lhs_nr;
  620.               int fc = (ii - fr) / lhs_nr;
  621.               lhs.elem (fr, fc) = rhs.elem (i, j);
  622.             }
  623.             }
  624.         }
  625.           else
  626.         {
  627.           (*current_liboctave_error_handler)
  628.       ("A(I) = X: X must be a scalar or a matrix with the same size as I");
  629.  
  630.           retval = 0;
  631.         }
  632.         }
  633.       // idx_vector::freeze() printed an error message for us.
  634.     }
  635.       else
  636.     {
  637.       (*current_liboctave_error_handler)
  638.         ("single index only valid for row or column vector");
  639.  
  640.       retval = 0;
  641.     }
  642.     }
  643.   else
  644.     {
  645.       (*current_liboctave_error_handler)
  646.     ("invalid number of indices for matrix expression");
  647.  
  648.       retval = 0;
  649.     }
  650.  
  651.   lhs.clear_index ();
  652.  
  653.   return retval;
  654. }
  655.  
  656. /*
  657. ;;; Local Variables: ***
  658. ;;; mode: C++ ***
  659. ;;; End: ***
  660. */
  661.